/*
 * Copyright 2011 Clean GWT
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.cleanform.gwt.chinesechess.client.comet;

import java.util.List;

import com.cleanform.gwt.chinesechess.client.comet.ServerPushEvent.HasCometHandlers;
import com.cleanform.gwt.chinesechess.client.comet.ServerPushEvent.ServerPushEventHandler;
import com.cleanform.gwt.chinesechess.shared.action.Actions;
import com.cleanform.gwt.chinesechess.shared.comet.UserEvent;
import com.cleanform.gwt.json.client.CollectionDeserializer;
import com.cleanform.gwt.json.client.ReflectDeserializer;
import com.cleanform.gwt.web.client.Requests;
import com.cleanform.gwt.web.client.StatedCallback;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.http.client.Request;

/**
 * The client to poll comet events.
 * 
 * @author Jess
 * @version 1.0
 * @since 1.0
 */
public class CometClient extends StatedCallback implements HasCometHandlers {
	private static CometClient instance;

	public static CometClient getInstance() {
		if (instance == null) {
			instance = new CometClient();
		}
		return instance;
	}

	private String clientid;
	private boolean polling;

	private SimpleEventBus eventBus = new SimpleEventBus();

	private CometClient() {
	}

	@Override
	public HandlerRegistration addServerPushHandler(ServerPushEventHandler handler) {
		return eventBus.addHandler(ServerPushEvent.getType(), handler);
	}

	@Override
	public void fireEvent(GwtEvent<?> event) {
		eventBus.fireEvent(event);
	}

	@Override
	public void onError(Request request, Throwable exception) {
		polling = false;
		deferedPolling();
	}

	@Override
	protected void onSuccess(String result) {
		polling = false;
		ServerPushEvent.fire(this, (List<UserEvent>) CollectionDeserializer.get(ReflectDeserializer.get(UserEvent.class))
				.deserialize(result));
		deferedPolling();

	}

	/**
	 * Starts polling for a client.
	 * 
	 * @param clientid the client id
	 */
	public void startPolling(String clientid) {
		this.clientid = clientid;
		if (clientid != null && !polling) {
			poll();
		}
	}

	/**
	 * Stops polling.
	 */
	public void stopPolling() {
		clientid = null;
	}

	/**
	 * Continuously poll in a fixed delay.
	 */
	protected void deferedPolling() {
		Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {

			@Override
			public boolean execute() {
				startPolling(clientid);
				return false;
			}
		}, 2000);
	}

	/**
	 * Polls for comet events.
	 */
	protected void poll() {
		polling = true;
		String url = Requests.buildUrl(Actions.GAME_CONTROLLER, Actions.GET_COMET_EVENTS);
		Requests.postObject("gameController/getCometEvents.do", clientid, this);
	}

}
